package com.zlc.common.util.wrapper.lambda;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * 字段配置
 */
@Data
@Slf4j
public class LambdaSett {


    /**
     * 字符串
     */
    public static final int STR = 0;
    /**
     * 日期
     */
    public static final int DATE = 1;
    /**
     * 数字
     */
    public static final int NUMBER = 2;
    /**
     * 布尔
     */
    public static final int BOOLEAN = 3;
    /**
     * 字段
     */
    private Field field;
    /**
     * 字段类型
     */
    private int fieldType;
    /**
     * 字段名
     */
    private String filedName;

    private Class implClass;

    public LambdaSett(SerializedLambda lambda, String filedName) {
        this.implClass = lambda.getImplClass();
        field = getAccessibleField(lambda.getImplClass(), filedName);
        this.filedName = filedName;
        Class<?> type = field.getType();
        if (type == String.class) {
            fieldType = STR;
        } else if (type == Number.class || Number.class.isAssignableFrom(type)) {
            fieldType = NUMBER;
        } else if ((type == Date.class || Date.class.isAssignableFrom(type))
             || (type == LocalDateTime.class || LocalDateTime.class.isAssignableFrom(type))) {
            fieldType = DATE;
        }else if(type == Boolean.class || Boolean.class.isAssignableFrom(type)){
            fieldType = BOOLEAN;
        } else {
            throw new RuntimeException("Wrapper<T> 只能用于 number str date ");
        }
    }

    public static Field getAccessibleField(Class<?> clazz, final String fieldName) {
        for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                Field field = superClass.getDeclaredField(fieldName);
                makeAccessible(field);
                return field;
            } catch (NoSuchFieldException e) {//NOSONAR
                // Field不在当前类定义,继续向上转型
                throw new RuntimeException(e.getMessage());
            }
        }
        log.error("获取字段fieldName失败");
        throw new RuntimeException("获取字段fieldName失败");
    }

    public static void makeAccessible(Field field) {
        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
                .isFinal(field.getModifiers())) && !field.isAccessible()) {
            field.setAccessible(true);
        }
    }
}
